home *** CD-ROM | disk | FTP | other *** search
/ The Very Best of Atari Inside / The Very Best of Atari Inside 1.iso / mint / mntlib43 / mntlib / doprnt.c < prev    next >
C/C++ Source or Header  |  1993-10-11  |  28KB  |  1,226 lines

  1. /*
  2.  * Copyright (c) 1988 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms are permitted
  6.  * provided that the above copyright notice and this paragraph are
  7.  * duplicated in all such forms and that any documentation,
  8.  * advertising materials, and other materials related to such
  9.  * distribution and use acknowledge that the software was developed
  10.  * by the University of California, Berkeley.  The name of the
  11.  * University may not be used to endorse or promote products derived
  12.  * from this software without specific prior written permission.
  13.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  14.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  15.  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  16.  */
  17.  
  18. /*
  19.  * minorly customized for gcc lib
  20.  *    ++jrb
  21.  * and for the sfp004 as well as the TT's 68881
  22.  *      mjr++
  23.  * and for turbo C and the MiNT library
  24.  *     ++um,mh
  25.  * and special M68881 and sfp004 version of cvt() added that uses fmovep for
  26.  * maximum precision, no bits lost anymore!
  27.  *    ++schwab
  28.  */
  29.  
  30. #ifndef __NO_FLOAT__
  31. #if 0
  32. static unsigned long
  33.     __notanumber[2] = { 0x7fffffffL, 0xffffffffL }; /* ieee NAN */
  34. #define NAN  (*((double *)&__notanumber[0]))
  35. static unsigned long
  36.     __p_infinity[2] = { 0x7ff00000L, 0x00000000L }; /* ieee NAN */
  37. #define INF  (*((double *)&__p_infinity[0]))
  38. #endif
  39.  
  40. #define NAN_HI 0x7fffffffL
  41. #define NAN_LO 0xffffffffL
  42. #define INF_HI 0x7ff00000L
  43. #define INF_LO 0x00000000L
  44.  
  45. #endif /* __NO_FLOAT__ */
  46.  
  47. #ifdef LIBC_SCCS
  48. static char sccsid[] = "@(#)doprnt.c    5.37 (Berkeley) 3/26/89";
  49. #endif /* LIBC_SCCS */
  50.  
  51. #include <compiler.h>
  52. #ifdef __TURBOC__
  53. #include <sys\types.h>
  54. #else
  55. #include <sys/types.h>
  56. #endif
  57. #include <stdarg.h>
  58. #include <stdio.h>
  59. #include <ctype.h>
  60. #include <string.h>
  61. #include <limits.h>
  62. #include <math.h>    /* mjr++ */
  63. #include "lib.h"
  64.  
  65. #ifndef __GNUC__    /* gcc lib has these typedefs in sys/types.h */
  66. #ifndef __MINT__    /* as does the MiNT library */
  67. typedef unsigned char u_char;
  68. typedef unsigned long u_long;
  69. #endif
  70. #endif
  71.  
  72. /* 11-bit exponent (VAX G floating point) is 308 decimal digits */
  73. #define    MAXEXP        308
  74.  
  75. /* 128 bit fraction takes up 39 decimal digits; max reasonable precision */
  76. # define    MAXFRACT    39
  77. # define    MAXEXP        308
  78.  
  79. #if defined (__M68881__) && !defined (sfp004)
  80. #  include <math-68881.h>    /* mjr: use the inline functions    */
  81. #endif    /* __M68881__ */
  82.  
  83. #define    DEFPREC        6
  84.  
  85. #define    BUF        (MAXEXP+MAXFRACT+1)    /* + decimal point */
  86.  
  87. #define    PUTC(ch)     if( (*putfunc)(ch, fp) == EOF ) return EOF;
  88.  
  89. #ifdef PRINTF_LONGLONG
  90. #define ARG(signtag) (\
  91.     (flags&LONGLONG ? \
  92.     (_ulonglong = (unsigned long long)va_arg(argp, signtag long long)) : 0 ) ,\
  93.     _ulong = \
  94.         flags&LONGLONG ? \
  95.             _ulonglong != 0ll : \
  96.         flags&LONGINT ? \
  97.             (unsigned long long)va_arg(argp, signtag long) : \
  98.         (flags&SHORTINT ? \
  99.             (unsigned long long)(signtag short)va_arg(argp, signtag int) : \
  100.              (unsigned long long)va_arg(argp, signtag int)) )
  101.      /* shorts are always promoted to ints; thus, it's `va_arg(... int)'
  102.       * for `flags&SHORTINT'!
  103.       */
  104. #else
  105. #define ARG(signtag) \
  106.     _ulong = \
  107.         flags&LONGINT ? \
  108.             (unsigned long)va_arg(argp, signtag long) : \
  109.         (flags&SHORTINT ? \
  110.             (unsigned long)(signtag short)va_arg(argp, signtag int) : \
  111.              (unsigned long)va_arg(argp, signtag int))
  112.      /* shorts are always promoted to ints; thus, it's `va_arg(... int)'
  113.       * for `flags&SHORTINT'!
  114.       */
  115. #endif
  116.  
  117. #define TEN_MUL(X)    ((((X) << 2) + (X)) << 1)
  118.  
  119. #define    todigit(c)    ((c) - '0')
  120. #define    tochar(n)    ((n) + '0')
  121.  
  122. #define    LONGINT        0x01        /* long integer */
  123. #define    LONGLONG    0x02        /* long long integer (8 bytes) */
  124. #define    LONGDBL        0x04        /* long double; unimplemented */
  125. #define    SHORTINT    0x08        /* short integer */
  126. #define    ALT        0x10        /* alternate form */
  127. #define    LADJUST        0x20        /* left adjustment */
  128. #define    ZEROPAD        0x40        /* zero (as opposed to blank) pad */
  129. #define    HEXPREFIX    0x80        /* add 0x or 0X prefix */
  130.  
  131. #ifndef __NO_FLOAT__
  132. #define __FLOATS__ 1
  133. #endif
  134.  
  135. #ifdef __FLOATS__
  136. # include    "flonum.h"
  137. #if defined (__M68881__) || defined (sfp004)
  138. static char *exponent __PROTO ((char *, int, int));
  139. static int _round __PROTO ((int, char *, char *, char *));
  140. static int cvt __PROTO ((double, int, int, char *, int, char *));
  141. #else
  142. #  if __STDC__
  143. static char *exponent(char *, int, int);
  144. static char *_round(double, int *, char *, char *, int, char *);
  145. static int  cvt(double, int, int, char *, int, char *, char *);
  146. #  else
  147. static char *exponent();
  148. static char *_round();
  149. static int  cvt();
  150. #  endif
  151. #endif /* __M68881__ */
  152. #endif
  153.  
  154. #if defined(__GNUC__) && (!defined(__NO_INLINE__))
  155. #ifdef __M68020__
  156.  
  157. #define _ICONV(NUMBER, BASE, BUF)                \
  158. {                                \
  159.   long i;                            \
  160.   do                                \
  161.     {                                \
  162.       __asm__ volatile                        \
  163.     ("divull %3,%1:%0"                    \
  164.      : "=d"((long)(NUMBER)), "=d"(i)            \
  165.      : "0"((long)(NUMBER)), "d"((long)(BASE)));        \
  166.       *--(BUF) = digs[i];                    \
  167.     }                                \
  168.   while (NUMBER);                        \
  169. }
  170.  
  171. #else /* !__M68020 */  
  172.  
  173. #define _ICONV(NUMBER, BASE, BUF)                 \
  174. {                                \
  175.                                 \
  176.     while((NUMBER) > 65535L)                    \
  177.     {                                \
  178.         extern unsigned long __udivsi3(); /* quot = d0, rem = d1 */ \
  179.         register long i __asm ("d1");                    \
  180.     __asm__ volatile("
  181.         movl    %3,sp@-;
  182.          movl    %2,sp@-;
  183.          jsr    ___udivsi3;
  184.          addqw    #8,sp;
  185.          movl    d0,%0"                    \
  186.              : "=r"((long)NUMBER), "=d"(i)            \
  187.          : "0"((long)NUMBER), "r"((long)BASE)        \
  188.              : "d0", "d1", "a0", "a1");            \
  189.         *--BUF = digs[i];                    \
  190.     }                                \
  191.     do                                 \
  192.     {                                \
  193.             short i;                        \
  194.         __asm__ volatile("
  195.          divu    %3,%2;
  196.          swap    %0;
  197.          movw    %0,%1;
  198.          clrw    %0;
  199.                 swap    %0"                    \
  200.              : "=d"((long)NUMBER), "=g"(i)            \
  201.          : "0"((long)NUMBER), "dm"((short)BASE));    \
  202.         *--BUF = digs[i];                    \
  203.     } while(NUMBER);                        \
  204. }
  205.  
  206. #endif /* __M68020 */
  207.  
  208. #else /* !__GNUC__ */
  209.  
  210. #define _ICONV(NUMBER, BASE, BUF)                 \
  211.   do {                                \
  212.     *--(BUF) = digs[(NUMBER) % (BASE)];                \
  213.     (NUMBER) /= (BASE);                        \
  214.   } while (NUMBER);
  215.  
  216. #endif /* __GNUC__ */
  217.  
  218. #ifdef PRINTF_LONGLONG
  219. #define _ICONVLL(NUMBER, BASE, BUF)                 \
  220.   do {                                \
  221.     *--(BUF) = digs[(NUMBER) % (BASE)];                \
  222.     (NUMBER) /= (BASE);                        \
  223.   } while (NUMBER);
  224. #endif
  225.  
  226. int _doprnt(putfunc, fp, fmt0, argp)
  227.     int (*putfunc) __PROTO ((int, FILE *));
  228.     FILE *fp;
  229.     const char *fmt0;
  230.     va_list argp;
  231. {
  232.     register const u_char *fmt;    /* format string */
  233.     register int ch;    /* character from fmt */
  234.     register int cnt;    /* return value accumulator */
  235.     register int n;        /* random handy integer */
  236.     register char *t;    /* buffer pointer */
  237. #ifdef    __FLOATS__
  238. /*    double _double;        *//* double precision arguments %[eEfgG] */
  239.     union double_di _dd;    /* _double is #defined to be _dd later on */
  240.     char softsign;        /* temporary negative sign for floats */
  241. #endif    /* __FLOATS__ */
  242. #ifdef PRINTF_LONGLONG
  243.     typedef unsigned long long _ulonglongtype;
  244.     typedef long long _ulonglongsignedtype;
  245.     _ulonglongtype _ulonglong;
  246. #endif
  247.     typedef u_long _ulongtype;
  248.     typedef long _ulongsignedtype;
  249.     _ulongtype _ulong;        /* integer arguments %[diouxX] */
  250.     short base;        /* base for [diouxX] conversion */
  251.     short dprec;        /* decimal precision in [diouxX] */
  252.     short fieldsz;        /* field size expanded by sign, etc */
  253.     short flags;        /* flags as above */
  254.     short fpprec;        /* `extra' floating precision in [eEfgG] */
  255.     short prec;        /* precision from format (%.3d), or -1 */
  256.     short realsz;        /* field size expanded by decimal precision */
  257.     short size;        /* size of converted field or string */
  258.     short width;        /* width from format (%8d), or 0 */
  259.     char sign;        /* sign prefix (' ', '+', '-', or \0) */
  260.     char *digs;        /* digits for [diouxX] conversion */
  261.     char buf[BUF];        /* space for %c, %[diouxX], %[eEfgG] */
  262.  
  263.     fmt = (const u_char *) fmt0;
  264.     digs = "0123456789abcdef";
  265.     for (cnt = 0;; ++fmt) {
  266.         if ((ch = *fmt) == 0)
  267.             return (cnt);
  268.         if (ch != '%') {
  269.             PUTC(ch);
  270.             cnt++;
  271.             continue;
  272.         }
  273.         flags = 0; dprec = 0; fpprec = 0; width = 0;
  274.         prec = -1;
  275.         sign = '\0';
  276.  
  277. rflag:        switch (*++fmt) {
  278.         case ' ':
  279.             /*
  280.              * ``If the space and + flags both appear, the space
  281.              * flag will be ignored.''
  282.              *    -- ANSI X3J11
  283.              */
  284.             if (!sign)
  285.                 sign = ' ';
  286.             goto rflag;
  287.         case '#':
  288.             flags |= ALT;
  289.             goto rflag;
  290.         case '*':
  291.             /*
  292.              * ``A negative field width argument is taken as a
  293.              * - flag followed by a  positive field width.''
  294.              *    -- ANSI X3J11
  295.              * They don't exclude field widths read from args.
  296.              */
  297.             if ((width = (short)(va_arg(argp, int))) >= 0)
  298.                 goto rflag;
  299.             width = -width;
  300.             /* FALLTHROUGH */
  301.         case '-':
  302.             flags |= LADJUST;
  303.             goto rflag;
  304.         case '+':
  305.             sign = '+';
  306.             goto rflag;
  307.         case '.':
  308.             if (*++fmt == '*')
  309.                 n = va_arg(argp, int);
  310.             else {
  311.                 n = 0;
  312.                 while (isascii(*fmt) && isdigit(*fmt))
  313.                     n = TEN_MUL(n) + todigit(*fmt++);
  314.                 --fmt;
  315.             }
  316.             prec = n < 0 ? -1 : n;
  317.             goto rflag;
  318.         case '0':
  319.             /*
  320.              * ``Note that 0 is taken as a flag, not as the
  321.              * beginning of a field width.''
  322.              *    -- ANSI X3J11
  323.              */
  324.             flags |= ZEROPAD;
  325.             goto rflag;
  326.         case '1': case '2': case '3': case '4':
  327.         case '5': case '6': case '7': case '8': case '9':
  328.             n = 0;
  329.             do {
  330.                 n = TEN_MUL(n) + todigit(*fmt);
  331.             } while (isascii(*++fmt) && isdigit(*fmt));
  332.             width = n;
  333.             --fmt;
  334.             goto rflag;
  335.         case 'L':
  336.             flags |= LONGDBL;
  337.             goto rflag;
  338.         case 'h':
  339.             flags |= SHORTINT;
  340.             goto rflag;
  341.         case 'l':
  342. #ifdef PRINTF_LONGLONG
  343.             if (flags & (LONGINT|LONGLONG))
  344.                 flags &= -1-LONGINT, flags |= LONGLONG;
  345.             else
  346. #endif
  347.                 flags |= LONGINT;
  348.             goto rflag;
  349.         case 'c':
  350.             *(t = buf) = va_arg(argp, int);
  351.             size = 1;
  352.             sign = '\0';
  353.             goto pforw;
  354.         case 'D':
  355. #ifdef PRINTF_LONGLONG
  356.             if (flags & (LONGINT|LONGLONG))
  357.                 flags &= -1-LONGINT, flags |= LONGLONG;
  358.             else
  359. #endif
  360.                 flags |= LONGINT;
  361.             /*FALLTHROUGH*/
  362.         case 'd':
  363.         case 'i':
  364.             ARG(signed);
  365. #ifdef PRINTF_LONGLONG
  366.             if (flags & LONGLONG) {
  367.                 if ((_ulonglongsignedtype)_ulonglong < 0ll) {
  368.                     _ulonglong = -_ulonglong;
  369.                     sign = '-';
  370.                 }
  371.             }
  372.             else
  373. #endif
  374.                 if ((_ulongsignedtype)_ulong < 0) {
  375.                     _ulong = -(long)_ulong;
  376.                     sign = '-';
  377.                 }
  378.             base = 10;
  379.             goto number;
  380. #ifdef __FLOATS__
  381.         case 'e':
  382.         case 'E':
  383.         case 'f':
  384.         case 'g':
  385.         case 'G':
  386.  
  387. /* mjr: check for NANs */
  388. #define    _double _dd.d
  389.             _double = va_arg(argp, double);
  390.             if (_dd.i[0] == NAN_HI)
  391.             {
  392.                 t = buf;
  393.                 t = strcpy(t, "NaN");
  394.                 size = strlen(t);
  395.                 goto pforw;
  396.             }
  397.             /*
  398.              * don't do unrealistic precision; just pad it with
  399.              * zeroes later, so buffer size stays rational.
  400.              */
  401.             if (prec > (MAXEXP - MAXFRACT)) {
  402.                 if ((*fmt != 'g' && *fmt != 'G') || (flags&ALT))
  403.                     fpprec = prec - MAXFRACT;
  404.                 prec = MAXFRACT;
  405.             }
  406.             else if (prec == -1)
  407.                 prec = DEFPREC;
  408.             /*
  409.              * softsign avoids negative 0 if _double is < 0 and
  410.              * no significant digits will be shown
  411.              */
  412.             if (_double < 0) {
  413.                 softsign = '-';
  414.                 _double = -_double;
  415.             }
  416.             else
  417.                 softsign = 0;
  418. /* hyc: check for overflows ... */
  419.             if ((((unsigned long)_dd.i[0] > INF_HI) &&
  420. /* mj: check for a negative zero; it is not smaller than zero, so it
  421.    was not negated */
  422.                  (_dd.i[0] != 0x80000000L || _dd.i[1] != 0)) ||
  423.                 ((unsigned long)_dd.i[0] == INF_HI &&
  424.                  (unsigned long)_dd.i[1] > INF_LO))
  425.               {
  426.                 t = buf;
  427.                 if(softsign == 0)
  428.                 t = strcpy(t, "NaN");
  429.                 else
  430.                 t = strcpy(t, "-NaN");
  431.                 size = strlen(t);
  432.                 goto pforw;
  433.             }
  434.             else    /* Not greater, see if equal to Inf */
  435.  
  436. /* mjr: check for +-INFINITY */
  437.             if ((unsigned long)_dd.i[0] == INF_HI)
  438.               {
  439.                 t = buf;
  440.                 if(softsign == 0)
  441.                 t = strcpy(t, "+Inf");
  442.                 else
  443.                 t = strcpy(t, "-Inf");
  444.                 size = strlen(t);
  445.                 goto pforw;
  446.             }
  447.             /*
  448.              * cvt may have to round up past the "start" of the
  449.              * buffer, i.e. ``printf("%.2f", (double)9.999);'';
  450.              * if the first char isn't '\0', it did.
  451.              */
  452.             *buf = '\0';
  453.             size = cvt(_double, (int)prec, (int)flags, &softsign,
  454.                    *fmt, buf
  455. #if !defined (__M68881__) && !defined (sfp004)
  456.                    , buf + (int)sizeof(buf)
  457. #endif
  458.                    ); 
  459.             if (softsign)
  460.                 sign = '-';
  461.             t = *buf ? buf : buf + 1;
  462.             goto pforw;
  463. #endif /* __FLOATS__ */
  464.         case 'n':
  465. #ifdef PRINTF_LONGLONG
  466.             if (flags & LONGLONG)
  467.                 *va_arg(argp, long long *) = cnt;
  468.             else
  469. #endif
  470.             if (flags & LONGINT)
  471.                 *va_arg(argp, long *) = cnt;
  472.             else if (flags & SHORTINT)
  473.                 *va_arg(argp, short *) = cnt;
  474.             else
  475.                 *va_arg(argp, int *) = cnt;
  476.             break;
  477.         case 'O':
  478. #ifdef PRINTF_LONGLONG
  479.             if (flags & (LONGINT|LONGLONG))
  480.                 flags &= -1-LONGINT, flags |= LONGLONG;
  481.             else
  482. #endif
  483.                 flags |= LONGINT;
  484.             /*FALLTHROUGH*/
  485.         case 'o':
  486.             ARG(unsigned);
  487.             base = 8;
  488.             goto nosign;
  489.         case 'p':
  490.             /*
  491.              * ``The argument shall be a pointer to void.  The
  492.              * value of the pointer is converted to a sequence
  493.              * of printable characters, in an implementation-
  494.              * defined manner.''
  495.              *    -- ANSI X3J11
  496.              */
  497.             /* NOSTRICT */
  498.             _ulong = (_ulongtype)va_arg(argp, void *);
  499. #ifdef PRINTF_LONGLONG
  500.             flags &= -1-LONGLONG;
  501. #endif
  502.             base = 16;
  503.             goto nosign;
  504.         case 's':
  505.             if ((t = va_arg(argp, char *)) == 0)
  506.                 t = "(null)";
  507.             if (prec >= 0) {
  508.                 /*
  509.                  * can't use strlen; can only look for the
  510.                  * NUL in the first `prec' characters, and
  511.                  * strlen() will go further.
  512.                  */
  513. #ifdef __STDC__
  514.                 char *p;
  515.                 void *memchr(const void *, int, size_t);
  516. #else
  517.                 char *p, *memchr();
  518. #endif
  519.  
  520.                 if ((p = (char *)memchr(t, 0, (size_t)prec)) != NULL) {
  521.                     size = (short)(p - t);
  522.                     if (size > prec)
  523.                         size = prec;
  524.                 } else
  525.                     size = prec;
  526.             } else
  527.                 size = (int)strlen(t);
  528.             sign = '\0';
  529.             goto pforw;
  530.         case 'U':
  531. #ifdef PRINTF_LONGLONG
  532.             if (flags & (LONGINT|LONGLONG))
  533.                 flags &= -1-LONGINT, flags |= LONGLONG;
  534.             else
  535. #endif
  536.                 flags |= LONGINT;
  537.             /*FALLTHROUGH*/
  538.         case 'u':
  539.             ARG(unsigned);
  540.             base = 10;
  541.             goto nosign;
  542.         case 'X':
  543.             digs = "0123456789ABCDEF";
  544.             /* FALLTHROUGH */
  545.         case 'x':
  546.             ARG(unsigned);
  547.             base = 16;
  548.             /* leading 0x/X only if non-zero */
  549.             /* Note: this does also work with _ulonglong, as we set
  550.                _ulong = 0 iff _ulonglong==0  --bjarne */
  551.             if (flags & ALT && _ulong != 0)
  552.                 flags |= HEXPREFIX;
  553.  
  554.             /* unsigned conversions */
  555. nosign:            sign = '\0';
  556.             /*
  557.              * ``... diouXx conversions ... if a precision is
  558.              * specified, the 0 flag will be ignored.''
  559.              *    -- ANSI X3J11
  560.              */
  561. number:            if ((dprec = prec) >= 0)
  562.                 flags &= ~ZEROPAD;
  563.  
  564.             /*
  565.              * ``The result of converting a zero value with an
  566.              * explicit precision of zero is no characters.''
  567.              *    -- ANSI X3J11
  568.              */
  569.             t = buf + BUF;
  570.             /* Note: this does also work with _ulonglong, as we set
  571.                _ulong = 0 iff _ulonglong==0  --bjarne */
  572.             if (_ulong != 0 || prec != 0) {
  573. #ifdef PRINTF_LONGLONG
  574.                 if (flags & LONGLONG) {
  575.                     _ICONVLL(_ulonglong, base, t);
  576.                 }
  577.                 /* As _ICONVLL might be a macro, we better put it in braces */
  578.                 else
  579. #endif
  580.                 {
  581.                     _ICONV(_ulong, base, t);
  582.                 }
  583.                 /* As _ICONV might be a macro, we better put it in braces */
  584.                 digs = "0123456789abcdef";
  585.                 if (flags & ALT && base == 8 && *t != '0')
  586.                     *--t = '0'; /* octal leading 0 */
  587.             }
  588.             size = (short)(buf + BUF - t);
  589.  
  590. pforw:
  591.             /*
  592.              * All reasonable formats wind up here.  At this point,
  593.              * `t' points to a string which (if not flags&LADJUST)
  594.              * should be padded out to `width' places.  If
  595.              * flags&ZEROPAD, it should first be prefixed by any
  596.              * sign or other prefix; otherwise, it should be blank
  597.              * padded before the prefix is emitted.  After any
  598.              * left-hand padding and prefixing, emit zeroes
  599.              * required by a decimal [diouxX] precision, then print
  600.              * the string proper, then emit zeroes required by any
  601.              * leftover floating precision; finally, if LADJUST,
  602.              * pad with blanks.
  603.              */
  604.  
  605.             /*
  606.              * compute actual size, so we know how much to pad
  607.              * fieldsz excludes decimal prec; realsz includes it
  608.              */
  609.             fieldsz = size + fpprec;
  610.             realsz = dprec > fieldsz ? dprec : fieldsz;
  611.             if (sign)
  612.                 realsz++;
  613.             if (flags & HEXPREFIX)
  614.                 realsz += 2;
  615.  
  616.             /* right-adjusting blank padding */
  617.             if ((flags & (LADJUST|ZEROPAD)) == 0 && width)
  618.                 for (n = realsz; n < width; n++)
  619.                     PUTC(' ');
  620.             /* prefix */
  621.             if (sign)
  622.                 PUTC(sign);
  623.             if (flags & HEXPREFIX) {
  624.                 PUTC('0');
  625.                 PUTC((char)*fmt);
  626.             }
  627.             /* right-adjusting zero padding */
  628.             if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD)
  629.                 for (n = realsz; n < width; n++)
  630.                     PUTC('0');
  631.             /* leading zeroes from decimal precision */
  632.             for (n = fieldsz; n < dprec; n++)
  633.                 PUTC('0');
  634.  
  635. #ifdef __FLOATS__
  636.             if (fpprec > 0)
  637.               {
  638.                 /* the number without exponent */
  639.                 n = size;
  640.                 while (*t != 'e' && *t != 'E' && --n >= 0)
  641.                   PUTC (*t++);
  642.               }
  643.             else
  644. #endif
  645.             /* the string or number proper */
  646.             for (n = size; --n >= 0; )
  647.                 PUTC(*t++);
  648.             /* trailing f.p. zeroes */
  649.             while (--fpprec >= 0)
  650.                 PUTC('0');
  651. #ifdef __FLOATS__
  652.             /* exponent */
  653.             while (--n >= 0)
  654.               PUTC (*t++);
  655. #endif
  656.             /* left-adjusting padding (always blank) */
  657.             if (flags & LADJUST)
  658.                 for (n = realsz; n < width; n++)
  659.                     PUTC(' ');
  660.             /* finally, adjust cnt */
  661.             cnt += width > realsz ? width : realsz;
  662.             break;
  663.         case '\0':    /* "%?" prints ?, unless ? is NULL */
  664.             return (cnt);
  665.         default:
  666.             PUTC((char)*fmt);
  667.             cnt++;
  668.         }
  669.     }
  670.     /* NOTREACHED */
  671. }
  672.  
  673. #ifdef __FLOATS__
  674. #if defined (__M68881__) || defined (sfp004)
  675.  
  676. /* Format of packed decimal (from left to right):
  677.  
  678.     1 Bit: sign of mantissa
  679.     1 Bit: sign of exponent
  680.     2 Bits zero
  681.    12 Bits: three digits exponent
  682.     4 Bits unused, fourth (higher order) digit of exponent
  683.     8 Bits zero
  684.    68 Bits: 17 digits of mantissa, decimal point after first digit
  685.   --------
  686.    96 Bits == 12 Bytes
  687.  
  688.    All numbers in BCD format.  */
  689.  
  690. #ifdef sfp004
  691. /* Note: not tested -- schwab */
  692.  
  693. /* static */ void Format __PROTO ((double number, char *buf));
  694.  
  695. asm (
  696. "comm = -6;\n"
  697. "resp = -16;\n"
  698. ".text\n"
  699. ".even\n"
  700. "_Format:\n"
  701. "    lea    0xfffffa50:w,a0            | fpu address\n"
  702. "    lea    sp@(4),a1            | argptr\n"
  703.  
  704. "    movew    #0x5400,a0@(comm)        | fmoved -> fp0\n"
  705. "1:    cmpw    #0x8900,a0@(resp)\n"
  706. "    beq    1b\n"
  707. "    movel    a1@+,a0@\n"
  708. "    movel    a1@+,a0@\n"
  709.  
  710. "    movel    a1@,a1                | get buf\n"
  711. "    movew    #0x6c11,a0@(comm)        | fmovep fp0,a1@{#17}\n"
  712. "1:    cmpw    #0x8900,a0@(resp)\n"
  713. "    beq    1b\n"
  714. "    movel    a0@,a1@+\n"
  715. "    movel    a0@,a1@+\n"
  716. "    movel    a0@,a1@+\n"
  717. "    rts\n"
  718. );
  719. #endif /* sfp004 */
  720.     
  721. static int
  722. cvt (number, prec, flags, signp, fmtch, startp)
  723.      double number;
  724.      int prec, flags, fmtch;
  725.      char *signp, *startp;
  726. {
  727.   char buf[12];
  728.   char digits[18];
  729.   int i;
  730.   char *p, *t;
  731.   int expcnt;
  732.   int gformat = 0, dotrim;
  733.  
  734.   /* Convert to packed decimal.  */
  735. #ifdef sfp004
  736.   Format (number, buf);
  737. #else
  738.   asm volatile ("fmovep %0,%1{#17}" : : "f" (number), "m" (buf[0]));
  739. #endif
  740.   /* Unpack it. */
  741.   p = buf + 3;
  742.   for (i = 0; i < 17; i++)
  743.     digits[i] = ((i & 1 ? *p >> 4 : *p++) & 15) + '0';
  744.   digits[i] = 0;
  745.   expcnt = ((buf[0] & 15) * 10 + ((buf[1] >> 4) & 15)) * 10 + (buf[1] & 15);
  746.   if (buf[0] & 0x40)
  747.     expcnt = -expcnt;
  748.   t = ++startp;
  749.   p = digits;
  750.   switch (fmtch)
  751.     {
  752.     case 'f':
  753.       if (expcnt >= 0)
  754.     {
  755.       *t++ = *p++;
  756.       while (expcnt > 0 && *p)
  757.         {
  758.           *t++ = *p++;
  759.           expcnt--;
  760.         }
  761.       while (expcnt > 0)
  762.         {
  763.           *t++ = '0';
  764.           expcnt--;
  765.         }
  766.     }
  767.       else
  768.     {
  769.       /* Note: decimal point after the first digit. */
  770.       expcnt++;
  771.       *t++ = '0';
  772.     }
  773.       if (prec || flags & ALT)
  774.     *t++ = '.';
  775.       while (prec > 0 && expcnt < 0)
  776.     {
  777.       *t++ = '0';
  778.       prec--;
  779.       expcnt++;
  780.     }
  781.       while (prec > 0 && *p)
  782.     {
  783.       *t++ = *p++;
  784.       prec--;
  785.     }
  786.       if (*p)
  787.     if (_round (*p, startp, t - 1, signp))
  788.       *--startp = '1';
  789.       while (prec > 0)
  790.     {
  791.       *t++ = '0';
  792.       prec--;
  793.     }
  794.       break;
  795.  
  796.     case 'e':
  797.     case 'E':
  798.     eformat:
  799.       *t++ = *p++;
  800.       if (prec || flags & ALT)
  801.     *t++ = '.';
  802.       while (prec > 0 && *p)
  803.     {
  804.       *t++ = *p++;
  805.       prec--;
  806.     }
  807.       if (*p)
  808.     if (_round (*p, startp, t - 1, signp))
  809.       {
  810.         expcnt++;
  811.         *startp = '1';
  812.       }
  813.       if (!gformat || flags & ALT)
  814.     {
  815.       while (prec > 0)
  816.         {
  817.           *t++ = '0';
  818.           prec--;
  819.         }
  820.     }
  821.       else
  822.     {
  823.       /* Suppress trailing zero's. */
  824.       while (t > startp && t[-1] == '0')
  825.         t--;
  826.       if (t[-1] == '.')
  827.         t--;
  828.     }
  829.       t = exponent (t, expcnt, fmtch);
  830.       break;
  831.  
  832.     case 'g':
  833.     case 'G':
  834.       if (prec == 0)
  835.     prec++;
  836.       /* If the exponent is not less than the precision or less than -4,
  837.      use 'e' format, otherwise use 'f' format.  */
  838.       if (expcnt >= prec || expcnt < -4)
  839.     {
  840.       /* Count the significant digit before the decimal point.  */
  841.       prec--;
  842.       /* 'g'/'G' -> 'e'/'E' */
  843.       fmtch -= 2;
  844.       gformat = 1;
  845.       goto eformat;
  846.     }
  847.       /* Like 'f', but prec counts significant digits.  */
  848.       if (expcnt >= 0)
  849.     {
  850.       *t++ = *p++;
  851.       prec--;
  852.       /* Note that prec >= expcnt */
  853.       while (expcnt > 0 && *p)
  854.         {
  855.           *t++ = *p++;
  856.           expcnt--;
  857.           prec--;
  858.         }
  859.       while (expcnt > 0)
  860.         {
  861.           *t++ = '0';
  862.           expcnt--;
  863.           prec--;
  864.         }
  865.     }
  866.       else
  867.     {
  868.       *t++ = '0';
  869.       expcnt++;
  870.     }
  871.       if (prec > 0 || flags & ALT)
  872.     {
  873.       dotrim = 1;
  874.       *t++ = '.';
  875.     }
  876.       else
  877.     dotrim = 0;
  878.       if (prec > 0)
  879.     /* Pad with 0's */
  880.     while (expcnt < 0)
  881.       {
  882.         *t++ = '0';
  883.         expcnt++;
  884.       }
  885.       /* While more precision required and digits left */
  886.       while (prec > 0 && *p)
  887.     {
  888.       *t++ = *p++;
  889.       prec--;
  890.     }
  891.       if (*p)
  892.     if (_round (*p, startp, t - 1, signp))
  893.       /* Overflow, e.g. 9.999 -> 10.000 */
  894.       *--startp = '1';
  895.       if (flags & ALT)
  896.     {
  897.       while (prec > 0)
  898.         {
  899.           *t++ = '0';
  900.           prec--;
  901.         }
  902.     }
  903.       else if (dotrim)
  904.     {
  905.       /* Strip trailing 0's. */
  906.       while (t > startp && *--t == '0');
  907.       if (*t != '.')
  908.         t++;
  909.     }
  910.       break;
  911.     }
  912.   return (int) (t - startp);
  913. }
  914.  
  915. static int
  916. _round (nxtdig, start, end, signp)
  917.      int nxtdig;
  918.      char *start, *end;
  919.      char *signp;
  920. {
  921.   if (nxtdig > '4')
  922.     {
  923.       for (;; --end)
  924.     {
  925.       if (*end == '.')
  926.         --end;
  927.       if (++*end <= '9')
  928.         break;
  929.       *end = '0';
  930.       if (end == start)
  931.         /* Report overflow, caller must handle appropriately.  */
  932.         return 1;
  933.     }
  934.     }
  935.   else if (*signp == '-')
  936.     {
  937.       for (;; --end)
  938.     {
  939.       if (*end == '.')
  940.         --end;
  941.       if (*end != '0')
  942.         break;
  943.       if (end == start)
  944.         *signp = 0;
  945.     }
  946.     }
  947.   return 0;
  948. }
  949.  
  950. #else /* !(__M68881__ || sfp004) */
  951.  
  952. static int
  953. cvt(number,prec,flags, signp, fmtch, startp, endp)
  954.     double number;
  955.     register int prec;
  956.     int flags;
  957.     int fmtch;
  958.     char *signp, *startp, *endp;
  959. {
  960.     register char *p, *t;
  961.     register double fract;
  962.     int dotrim, expcnt, gformat;
  963.     double integer, tmp, modf __PROTO((double, double *));
  964.     char *exponent __PROTO((char *, int, int)),
  965.          *_round __PROTO((double, int *, char *, char *, int, char *));
  966.  
  967.     dotrim = expcnt = gformat = 0;
  968.     fract = modf(number, &integer);
  969.  
  970.     /* get an extra slot for rounding. */
  971.     t = ++startp;
  972. /* jrb -- #define DBL_EPSILON 1.1107651257113995e-16 */ /* mjr ++ */
  973.     /*
  974.      * get integer portion of number; put into the end of the buffer; the
  975.      * .01 is added for modf(356.0 / 10, &integer) returning .59999999...
  976.      */
  977.     for (p = endp - 1; integer; ++expcnt) {
  978.         tmp = modf(integer / 10, &integer);
  979.         *p-- = tochar((int)((tmp + .01) * 10));
  980. /* await michals advise on this    -- in the mean while use above line
  981.     *p-- = tochar((int)((tmp + DBL_EPSILON) * 10));
  982.  */
  983.     }
  984.     switch(fmtch) {
  985.     case 'f':
  986.         /* reverse integer into beginning of buffer */
  987.         if (expcnt)
  988.             for (; ++p < endp; *t++ = *p);
  989.         else
  990.             *t++ = '0';
  991.         /*
  992.          * if precision required or alternate flag set, add in a
  993.          * decimal point.
  994.          */
  995.         if (prec || flags&ALT)
  996.             *t++ = '.';
  997.         /* if requires more precision and some fraction left */
  998.         if (fract) {
  999.             if (prec)
  1000.                 do {
  1001.                     fract = modf(fract * 10, &tmp);
  1002.                     *t++ = tochar((int)tmp);
  1003.                 } while (--prec && fract);
  1004.             if (fract)
  1005.                 startp = _round(fract, (int *)NULL, startp,
  1006.                     t - 1, (char)0, signp);
  1007.         }
  1008.         for (; prec--; *t++ = '0');
  1009.         break;
  1010.     case 'e':
  1011.     case 'E':
  1012. eformat:    if (expcnt) {
  1013.             *t++ = *++p;
  1014.             if (prec || flags&ALT)
  1015.                 *t++ = '.';
  1016.             /* if requires more precision and some integer left */
  1017.             for (; prec && ++p < endp; --prec)
  1018.                 *t++ = *p;
  1019.             /*
  1020.              * if done precision and more of the integer component,
  1021.              * round using it; adjust fract so we don't re-round
  1022.              * later.
  1023.              */
  1024.             if (!prec && ++p < endp) {
  1025.                 fract = 0;
  1026.                 startp = _round((double)0, &expcnt, startp,
  1027.                     t - 1, *p, signp);
  1028.             }
  1029.             /* adjust expcnt for digit in front of decimal */
  1030.             --expcnt;
  1031.         }
  1032.         /* until first fractional digit, decrement exponent */
  1033.         else if (fract) {
  1034.             /* adjust expcnt for digit in front of decimal */
  1035.             for (expcnt = -1;; --expcnt) {
  1036.                 fract = modf(fract * 10, &tmp);
  1037.                 if (tmp)
  1038.                     break;
  1039.             }
  1040.             *t++ = tochar((int)tmp);
  1041.             if (prec || flags&ALT)
  1042.                 *t++ = '.';
  1043.         }
  1044.         else {
  1045.             *t++ = '0';
  1046.             if (prec || flags&ALT)
  1047.                 *t++ = '.';
  1048.         }
  1049.         /* if requires more precision and some fraction left */
  1050.         if (fract) {
  1051.             if (prec)
  1052.                 do {
  1053.                     fract = modf(fract * 10, &tmp);
  1054.                     *t++ = tochar((int)tmp);
  1055.                 } while (--prec && fract);
  1056.             if (fract)
  1057.                 startp = _round(fract, &expcnt, startp,
  1058.                     t - 1, (char)0, signp);
  1059.         }
  1060.         /* if requires more precision */
  1061.         for (; prec--; *t++ = '0');
  1062.  
  1063.         /* unless alternate flag, trim any g/G format trailing 0's */
  1064.         if (gformat && !(flags&ALT)) {
  1065.             while (t > startp && *--t == '0');
  1066.             if (*t == '.')
  1067.                 --t;
  1068.             ++t;
  1069.         }
  1070.         t = exponent(t, expcnt, fmtch);
  1071.         break;
  1072.     case 'g':
  1073.     case 'G':
  1074.         /* a precision of 0 is treated as a precision of 1. */
  1075.         if (!prec)
  1076.             ++prec;
  1077.         /*
  1078.          * ``The style used depends on the value converted; style e
  1079.          * will be used only if the exponent resulting from the
  1080.          * conversion is less than -4 or greater than the precision.''
  1081.          *    -- ANSI X3J11
  1082.          */
  1083.         if (expcnt > prec || (!expcnt && fract && fract < .0001)) {
  1084.             /*
  1085.              * g/G format counts "significant digits, not digits of
  1086.              * precision; for the e/E format, this just causes an
  1087.              * off-by-one problem, i.e. g/G considers the digit
  1088.              * before the decimal point significant and e/E doesn't
  1089.              * count it as precision.
  1090.              */
  1091.             --prec;
  1092.             fmtch -= 2;        /* G->E, g->e */
  1093.             gformat = 1;
  1094.             goto eformat;
  1095.         }
  1096.         /*
  1097.          * reverse integer into beginning of buffer,
  1098.          * note, decrement precision
  1099.          */
  1100.         if (expcnt)
  1101.             for (; ++p < endp; *t++ = *p, --prec);
  1102.         else
  1103.             *t++ = '0';
  1104.         /*
  1105.          * if precision required or alternate flag set, add in a
  1106.          * decimal point.  If no digits yet, add in leading 0.
  1107.          */
  1108.         if (prec || flags&ALT) {
  1109.             dotrim = 1;
  1110.             *t++ = '.';
  1111.         }
  1112.         else
  1113.             dotrim = 0;
  1114.         /* if requires more precision and some fraction left */
  1115.         if (fract) {
  1116.             if (prec) {
  1117.                 if (0 == expcnt) {
  1118.                     /* if no significant digits yet */
  1119.                     do {
  1120.                         fract = modf(fract * 10, &tmp);
  1121.                         *t++ = tochar((int)tmp);
  1122.                     } while(!tmp);
  1123.                     prec--;
  1124.                 }
  1125.                 while (prec && fract) {
  1126.                     fract = modf(fract * 10, &tmp);
  1127.                     *t++ = tochar((int)tmp);
  1128.                     prec--;
  1129.                 }
  1130.             }
  1131.             if (fract)
  1132.                 startp = _round(fract, (int *)NULL, startp,
  1133.                     t - 1, (char)0, signp);
  1134.         }
  1135.         /* alternate format, adds 0's for precision, else trim 0's */
  1136.         if (flags&ALT)
  1137.             for (; prec--; *t++ = '0');
  1138.         else if (dotrim) {
  1139.             while (t > startp && *--t == '0');
  1140.             if (*t != '.')
  1141.                 ++t;
  1142.         }
  1143.     }
  1144.     return((int)(t - startp));
  1145. }
  1146.  
  1147. static char *
  1148. _round(fract, exp, start, end, ch, signp)
  1149.     double fract;
  1150.     int *exp;
  1151.     register char *start, *end;
  1152.     int ch;
  1153.     char *signp;
  1154. {
  1155.     double tmp;
  1156.  
  1157.     if (fract)
  1158.         (void)modf(fract * 10, &tmp);
  1159.     else
  1160.         tmp = todigit(ch);
  1161.     if (tmp > 4)
  1162.         for (;; --end) {
  1163.             if (*end == '.')
  1164.                 --end;
  1165.             if (++*end <= '9')
  1166.                 break;
  1167.             *end = '0';
  1168.             if (end == start) {
  1169.                 if (exp) {    /* e/E; increment exponent */
  1170.                     *end = '1';
  1171.                     ++*exp;
  1172.                 }
  1173.                 else {        /* f; add extra digit */
  1174.                     *--end = '1';
  1175.                     --start;
  1176.                 }
  1177.                 break;
  1178.             }
  1179.         }
  1180.     /* ``"%.3f", (double)-0.0004'' gives you a negative 0. */
  1181.     else if (*signp == '-')
  1182.         for (;; --end) {
  1183.             if (*end == '.')
  1184.                 --end;
  1185.             if (*end != '0')
  1186.                 break;
  1187.             if (end == start)
  1188.                 *signp = 0;
  1189.         }
  1190.     return(start);
  1191. }
  1192.  
  1193. #endif /* !(__M68881__ || sfp004) */
  1194.  
  1195. static char *
  1196. exponent(p, exp, fmtch)
  1197.     register char *p;
  1198.     register int exp;
  1199.     int fmtch;
  1200. {
  1201.     register char *t;
  1202.     char expbuf[MAXEXP];
  1203.  
  1204.     *p++ = fmtch;
  1205.     if (exp < 0) {
  1206.         exp = -exp;
  1207.         *p++ = '-';
  1208.     }
  1209.     else
  1210.         *p++ = '+';
  1211.     t = expbuf + MAXEXP;
  1212.     if (exp > 9) {
  1213.         do {
  1214.             *--t = tochar(exp % 10);
  1215.         } while ((exp /= 10) > 9);
  1216.         *--t = tochar(exp);
  1217.         for (; t < expbuf + MAXEXP; *p++ = *t++);
  1218.     }
  1219.     else {
  1220.         *p++ = '0';
  1221.         *p++ = tochar(exp);
  1222.     }
  1223.     return(p);
  1224. }
  1225. #endif /* __FLOATS__ */
  1226.